package practica6.Problema8Reinas;

import framework.IBasicState;

public class StateReinas implements IBasicState {
    private StateReinas parent;
    private int[][] board = new int[8][8];/* tablero de ajedres */
    private int queensInBoard; /* cantidad de reinas en el tablero */
    private final int CENTINELA = 10;

    /**
     * estado inicial: tablero vacio
     */
    public StateReinas() {
	queensInBoard = 0;
	for (int i = 0; i < 8; i++) {
	    for (int j = 0; j < 8; j++) {
		board[i][j] = 0;
	    }
	}
    }

    public int[][] getTablero() {
	return board;
    }

    /**
     * coloca una reina (1) en el lugar determinado suma (1) la cantidad de
     * reinas e nel tablero
     * 
     * @param i
     * @param j
     */
    public void ponerReina(int i, int j) {
	queensInBoard++;
	board[i][j] = 1;
    }

    /**
     * es la primer fila que no contiene reinas
     * 
     * @return Int 0..7 ssi encontro una fila sin reina, sino 10
     */
    public int getFilaSinReina() {
	boolean noEncontre = true;
	for (int i = 0; i < 8; i++) {
	    noEncontre = true;
	    for (int j = 0; j < 8 && noEncontre; j++) {
		if (board[i][j] == 1) {
		    noEncontre = false;
		}
	    }
	    if (noEncontre) {
		return i;
	    }
	}
	return CENTINELA;
    }

    @Override
    public StateReinas clone() {
	StateReinas tableroNuevo = new StateReinas();
	tableroNuevo.parent = this.parent;
	for (int i = 0; i < 8; i++) {
	    for (int j = 0; j < 8; j++) {
		tableroNuevo.board[i][j] = this.board[i][j];
	    }
	}
	tableroNuevo.queensInBoard = this.queensInBoard;
	return tableroNuevo;
    }

    /**
     * Indica cual es el estado del cual deriva este estado
     * 
     * @return el estado del cual este estado deriva : {@code IBasicState} //
     *         <hr>
     *         <b>Solo la raíz tiene {@code parent == null}</b>
     */
    @Override
    public IBasicState getParent() {
	return this.parent;
    }

    @Override
    public boolean isFinal() {
	return noPuedoColocarMasReinas();
    }

    @Override
    public boolean repOk() {
	return true;
    }

    @Override
    public void setParent(IBasicState tablero) {
	this.parent = (StateReinas) tablero;
    }

    @Override
    public boolean success() {
	return (queensInBoard == 8 && !seRepelan());
    }

    private boolean noPuedoColocarMasReinas() {
	if (hayReinaEnElUltimoNivel() || seRepelan())
	    return true;
	else
	    return false;
    }

    private boolean hayReinaEnElUltimoNivel() {
	for (int j = 0; j < 8; j++) {// existe una reina (1) el la ultima Fila y
	    // no tengo 8 reinas
	    if (board[7][j] == 1)
		return true;

	}
	return false;
    }

    private boolean seRepelan() {
	boolean repela = false;
	for (int i = 7; i >= 0; i--) {
	    for (int j = 7; j >= 0; j--) {
		if (board[i][j] == 1) {
		    repela = repela(i, j);
		    if (repela) {
			return true;
		    }
		}

	    }
	}
	return repela;
    }

    /*
     * toma una posicion de una reina y retorna true ssi se repela con alguna
     * otra reina ubicada antes que esta
     */
    private boolean repela(int i, int j) {
	boolean rep = false;
	// diagonal hacia la izquierda
	int fi = (i - 1);
	int co = (j - 1);
	while (fi >= 0 && co >= 0 && fi < 8 && co < 8) {
	    if (board[fi][co] == 1)
		rep = true;
	    fi--;
	    co--;
	}

	fi = i - 1;
	co = j + 1;

	while (fi >= 0 && co < 8 && fi < 8 && co >= 0) {
	    if (board[fi][co] == 1)
		rep = true;
	    fi--;
	    co++;
	}

	for (int col = 0; col < j; col++) {// se fija en filas (i fijo)
	    if (board[i][col] == 1)
		rep = true;
	}
	for (int fil = 0; fil < i; fil++) {// se fija en columnas
	    if (board[fil][j] == 1)
		rep = true;
	}

	return rep;
    }

    public String toString() {
	String newS = new String("**[");

	int[][] t = board;
	for (int i = 0; i < 8; i++) {
	    for (int j = 0; j < 8; j++) {
		if (t[i][j] == 1) {
		    newS = newS + "( " + i + j + ") ";
		}
	    }
	}
	return newS + "]**";
    }

}
